package elijah.eupdater.utils;

import android.content.Context;
import android.text.TextUtils;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPClientConfig;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import elijah.eupdater.Constants;
import elijah.eupdater.Progress;
import elijah.eupdater.Eupdater;
import elijah.eupdater.bean.TerminalDevice;
import elijah.eupdater.bean.UpdaterConfig;
import io.reactivex.Observable;

public class FtpUtils {


    public static Observable<Progress> addNewDownload(Context context, TerminalDevice terminalDevice) {
        return Observable.create(observer -> {
            FTPClient ftpClient = null;
            Progress progress = new Progress();
            try {
                UpdaterConfig config = Eupdater.get().getConfig();

                if (config == null || TextUtils.isEmpty(config.getFtpIp())) {
                    throw new IOException(Constants.FTP_CONNECT_FAIL);
                }



                List<FTPFile> files = new ArrayList<>();


                ftpClient = FtpUtils.openConnect(config, "UTF-8");
                String pathname = getFiles(ftpClient, terminalDevice.getUpdateFilePath(), files);
                if (files.size() == 0) {
                    files.clear();
                    ftpClient = FtpUtils.openConnect(config, "GBK");
                    pathname = getFiles(ftpClient, terminalDevice.getUpdateFilePath(), files);
                }
                if (files.size() == 0) {
                    throw new IOException(Constants.FTP_FILE_NOT_EXISTS);
                }


                FTPFile ftpFile = files.get(0);
                long serverSize = ftpFile.getSize();
                progress.setTotalSize(serverSize);
                observer.onNext(progress);

                File dir = new File(AppUtils.getUpdateFilePath(context));
                if (!dir.exists()) {
                    dir.mkdirs();
                }
                File localFile = new File(dir, terminalDevice.getUpdateFileName());
                if (localFile.exists()) {
                    localFile.delete();
                }

                BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(localFile));
                BufferedInputStream ins = new BufferedInputStream(ftpClient.retrieveFileStream(pathname));

                byte[] b = new byte[2048];
                int readLen;
                long step = serverSize / 100;
                float process;
                long currentSize = 0;
                long lastSize = 0;
                long lastTime = System.currentTimeMillis();
                while ((readLen = ins.read(b)) != -1) {
                    bos.write(b, 0, readLen);
                    currentSize = currentSize + readLen;

                    process = currentSize * 1f / step;
                    if ((int) (process * 100) % 10 == 0) {
                        progress.setProgress(process)
                                .setCurSize(currentSize);
                        observer.onNext(progress);
                    }

                    if (System.currentTimeMillis() - lastTime >= 1000) {
                        progress.setSpeed(currentSize - lastSize);
                        observer.onNext(progress);
                        lastSize = currentSize;
                        lastTime = System.currentTimeMillis();
                    }
                }
                ins.close();
                bos.close();
                boolean success = ftpClient.completePendingCommand();
                observer.onNext(progress.setCurSize(serverSize).setProgress(100));
                observer.onComplete();
                if (!success) {
                    throw new IOException(Constants.FTP_DOWN_FAIL);
                }
            } catch (Exception e) {
                observer.onError(e);
            } finally {
                closeConnect(ftpClient);
            }
        });
    }

    public static String getFiles(FTPClient ftpClient, String filePath, List<FTPFile> fileList) throws IOException {
        String pathname = filePath;
        FTPFile[] files = ftpClient.listFiles(pathname);
        if (files.length == 0) {
            pathname = new String(filePath.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
            files = ftpClient.listFiles(pathname);

        }
        if (files.length == 0) {
            pathname = new String(filePath.getBytes("gb2312"), StandardCharsets.ISO_8859_1);
            files = ftpClient.listFiles(pathname);

        }
        if (files.length == 0) {
            pathname = new String(filePath.getBytes("GBK"), StandardCharsets.ISO_8859_1);
            files = ftpClient.listFiles(pathname);
        }
        fileList.clear();
        if (files != null && files.length > 0) {
            fileList.addAll(Arrays.asList(files));
        }
        return pathname;
    }

    public static FTPClient openConnect(UpdaterConfig config, String encoding) throws IOException {
        // 中文转码
        FTPClient ftpClient = new FTPClient();
        ftpClient.setConnectTimeout(5000);
        ftpClient.setControlEncoding(encoding);

        int reply; // 服务器响应值
        // 连接至服务器
        ftpClient.connect(config.getFtpIp(), config.getFtpPort());
        // 获取响应值
        reply = ftpClient.getReplyCode();
        if (!FTPReply.isPositiveCompletion(reply)) {
            // 断开连接
            ftpClient.disconnect();
            throw new IOException("连接失败: " + reply);
        }
        // 登录到服务器
        ftpClient.login(config.getFtpUser(), config.getFtpPsw());
        // 获取响应值
        reply = ftpClient.getReplyCode();
        if (!FTPReply.isPositiveCompletion(reply)) {
            // 断开连接
            ftpClient.disconnect();
            throw new IOException("登录失败: " + reply);
        } else {
            // 获取登录信息
            FTPClientConfig clientConfig = new FTPClientConfig(ftpClient
                    .getSystemType().split(" ")[0]);
            clientConfig.setServerLanguageCode("zh");
            ftpClient.configure(clientConfig);
            // 使用被动模式设为默认
            ftpClient.enterLocalPassiveMode();
            // 二进制文件支持
            ftpClient
                    .setFileType(org.apache.commons.net.ftp.FTP.BINARY_FILE_TYPE);
        }
        return ftpClient;
    }

    /**
     * 关闭FTP服务.
     *
     * @throws IOException
     */
    public static void closeConnect(FTPClient ftpClient) {
        try {
            if (ftpClient != null) {
                // 退出FTP
                ftpClient.logout();
                // 断开连接
                ftpClient.disconnect();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
